#include <crt_util.h>

void _list_init(struct _list_s* self)
{
    self->first = NULL;
    self->last = NULL;
}

void _list_term(struct _list_s* self)
{
    rc_return(self->first == NULL);
    rc_return(self->last == NULL);
}

int _list_empty(struct _list_s* self)
{
    return self->first ? 0 : 1;
}

struct _list_item* _list_begin(struct _list_s* self)
{
    return self->first;
}

struct _list_item* _list_end(struct _list_s* self)
{
    return NULL;
}

struct _list_item* _list_prev(struct _list_s* self, struct _list_item* it)
{
    if (!it)
        return self->last;
    rc_error(it->prev != _LIST_NOTINLIST, NULL);
    return it->prev;
}

struct _list_item* _list_next(struct _list_s* self, struct _list_item* it)
{
    rc_error(it->next != _LIST_NOTINLIST, NULL);
    return it->next;
}

void _list_insert(struct _list_s* self, struct _list_item* item, struct _list_item* it)
{
    rc_return(!_list_item_isinlist(item));

    item->prev = it ? it->prev : self->last;
    item->next = it;
    if (item->prev)
        item->prev->next = item;
    if (item->next)
        item->next->prev = item;
    if (!self->first || self->first == it)
        self->first = item;
    if (!it)
        self->last = item;
}

struct _list_item* _list_erase(struct _list_s* self, struct _list_item* item)
{
    struct _list_item* next;

    rc_error(_list_item_isinlist(item), NULL);

    if (item->prev)
        item->prev->next = item->next;
    else
        self->first = item->next;
    if (item->next)
        item->next->prev = item->prev;
    else
        self->last = item->prev;

    next = item->next;

    item->prev = _LIST_NOTINLIST;
    item->next = _LIST_NOTINLIST;

    return next;
}

void _list_item_init(struct _list_item* self)
{
    self->prev = _LIST_NOTINLIST;
    self->next = _LIST_NOTINLIST;
}

void _list_item_term(struct _list_item* self)
{
    rc_return(!_list_item_isinlist(self));
}

int _list_item_isinlist(struct _list_item* self)
{
    return self->prev == _LIST_NOTINLIST ? 0 : 1;
}
